package cn.texous.util.commons.util.system;

import sun.misc.Signal;
import sun.misc.SignalHandler;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

/**
 * 优雅关闭 java 程序
 */
public class KillHandler implements SignalHandler {

    private Consumer<Signal> signalConsumer;
    private Integer linuxSign;

    public KillHandler(Consumer<Signal> signalConsumer, Integer linuxSign) {
        this.signalConsumer = signalConsumer;
        this.linuxSign = linuxSign;
    }

    public void start() {
        registerSignal(linuxSign);
    }

    private static final String getOsSignalType() {
        return isWinOs() ? "INT" : "TERM";
    }

    private static boolean isWinOs() {
        return System.getProperties().getProperty("os.name")
                .toLowerCase().startsWith("win");
    }

    /**
     * 注册信号只
     *
     * @param linuxSign 信号
     */
    public void registerSignal(Integer linuxSign) {
        Signal signal;
        if (isWinOs()) {
            signal = new Signal(getOsSignalType());
        } else {
            String signalName = "TERM";
            if (linuxSign != null) {
                switch (linuxSign) {
                    case 12:
                        signalName = "USR2";
                        break;
                    default:
                        break;
                }
            }
            signal = new Signal(signalName);
        }
        Signal.handle(signal, this);
    }

    @Override
    public void handle(Signal signal) {
        System.out.println("信号名称：" + signal.getName() + ", 信号编码：" + signal.getNumber());
        signalConsumer.accept(signal);
    }

    /**
     * 测试方法
     *
     * @param args 参数
     */
    public static void main(String[] args) {
        final AtomicBoolean flag = new AtomicBoolean(true);
        System.out.println("system start");
        new KillHandler(signal -> flag.set(false), null).start();
        while (flag.get()) {
            try {
                System.out.println("while start------");
                Thread.sleep(10000);
                System.out.println("while end-------");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("system end");
    }

}
